package org.sqlproc.engine;

import java.util.List;

import org.hibernate.HibernateException;

/**
 * The vehicle interface definition, which can be used to monitor the duration of all SQL queries execution.
 * 
 * <p>
 * The implementation can be based for example on the Javasimon library. Standard implementation is an empty one, which
 * just delegates the execution to the runner, for example
 * 
 * <pre>
 * public &lt;E&gt; List&lt;E&gt; runQuery(Runner runner, Class&lt;E&gt; resultClass) {
 *     return (List&lt;E&gt;) runner.run();
 * }
 * </pre>
 * 
 * <p>
 * For more info please see the User's tutorial.
 * 
 * @author <a href="mailto:Vladimir.Hudec@gmail.com">Vladimir Hudec</a>
 */
public interface SqlMonitor {

    /**
     * The SQLMonitor visitor method called from inside the
     * {@link SqlEngine#query(org.hibernate.Session, Class, Object, Object, SqlOrder, int, int, int)}.
     * 
     * @param runner
     *            the anonymous instance of {@link SqlMonitor.Runner}, which encapsulates the query execution
     * @param resultClass
     *            the class used for the return values of the query execution
     * @return the list of the resultClass instances
     */
    public <E> List<E> runQuery(Runner runner, Class<E> resultClass);

    /**
     * The SQLMonitor visitor method called from inside the
     * {@link SqlEngine#queryCount(org.hibernate.Session, Object, Object, SqlOrder, int)}.
     * 
     * @param runner
     *            the anonymous instance of {@link SqlMonitor.Runner}, which encapsulates the queryCount execution
     * @return the size of potential list of resultClass instances
     */
    public int runQueryCount(Runner runner);

    /**
     * The SQLMonitor visitor method called from inside the {@link SqlEngine#getSql(Object, Object, SqlOrder)}.
     * 
     * @param runner
     *            the anonymous instance of {@link SqlMonitor.Runner}, which encapsulates the getSql execution
     * @return the SQL query command derived from the META SQL based in input parameters
     */
    public String runGetSql(Runner runner);

    /**
     * This interface is implemented in {@link SqlEngine} main public methods. An anonymous instance of this interface
     * is used to encapsulate the SQL Processor application logic, and as a parameter is propagated to SQLMonitor
     * instance. This gives the SQLMonitor the opportunity to surround the SQL Processor execution with a duration
     * tracking code.
     */
    public static interface Runner {
        /**
         * The main contract, which is invoked from inside SQLMonitor
         * 
         * @return the value depends on from which method this contract is invoked
         * @throws HibernateException
         */
        Object run() throws HibernateException;
    }
}
